home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
tools
/
phwarp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
12KB
|
630 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* phwarp -
* Paul Heckbert and Paul Haeberli team up to warp images
* on a Silicon Graphics VGX machine.
*
* Paul Heckberli - 1990
*/
#include "stdio.h"
#include "math.h"
#include "gl.h"
#include "device.h"
#define DEFMESHRES (50)
#define MAXDIM (100)
#define RADSCALE (1.41)
#define WARP_POS (1)
#define WARP_SIZE (2)
float ease();
#define NKEYS (8)
float flerp();
float wfunc();
float ease();
float sqrt_sum_sq();
typedef struct {
float x, y;
} Point;
typedef struct {
Point orig, warp, wgt;
} warpPoint;
long oldxorg, oldyorg;
long oldxsize, oldysize;
long xsize, ysize;
int lastkey = -1;
int dim, drawgrid;
int warpmode = WARP_POS;
int nsteps = 20;
int fullmode = 0;
float warpradius, aspect;
warpPoint pt[MAXDIM][MAXDIM];
Point key[NKEYS][MAXDIM][MAXDIM];
Point tempkey[MAXDIM][MAXDIM];
FILE *movief;
readkeys(name)
char *name;
{
FILE *inf;
inf = fopen(name,"r");
if(!inf) {
fprintf(stderr,"readkeys: can't open input file %s\n",name);
exit(1);
}
fread(&key[0][0][0],1,NKEYS*MAXDIM*MAXDIM*sizeof(Point),inf);
fclose(inf);
}
writekeys(name)
char *name;
{
FILE *outf;
percentdone(50.0);
outf = fopen(name,"w");
if(!outf) {
fprintf(stderr,"readkeys: can't open input file %s\n",name);
exit(1);
}
fwrite(&key[0][0][0],1,NKEYS*MAXDIM*MAXDIM*sizeof(Point),outf);
fclose(outf);
percentdone(100.0);
}
float sqrt_sum_sq(x,y)
float x, y;
{
return fsqrt(x*x+y*y);
}
dofunc(n)
int n;
{
if(myshiftdown())
loadkey(n);
else
lerpkey(n);
}
loadkey(n)
int n;
{
int x, y;
fprintf(stderr,"loading key %d . . .",n+1);
for(y=0; y<dim; y++) {
for(x=0; x<dim; x++) {
key[n][y][x] = pt[y][x].warp;
}
}
fprintf(stderr,"done\n");
}
plerp(p0,p1,p,f)
Point *p0, *p1, *p;
float f;
{
p->x = flerp(p0->x,p1->x,f);
p->y = flerp(p0->y,p1->y,f);
}
setnsteps()
{
float f;
f = 1.0-(getvaluator(MOUSEY)/1024.0);
nsteps = flerp(3.0,50.0,f*f);
fprintf(stderr,"\rnsteps is %d ",nsteps);
}
lerpkey(n)
int n;
{
int i, x, y;
float f;
if(n == lastkey)
return;
fprintf(stderr,"lerping to key %d . . .",n+1);
percentdone(50.0);
for(y=0; y<dim; y++) {
for(x=0; x<dim; x++)
tempkey[y][x] = pt[y][x].warp;
}
for(i=0; i<nsteps; i++) {
f = i/(nsteps-1.0);
f = ease(f);
for(y=0; y<dim; y++) {
for(x=0; x<dim; x++)
plerp(&tempkey[y][x],&key[n][y][x],&pt[y][x].warp,f);
}
drawmesh();
}
percentdone(100.0);
fprintf(stderr,"done\n");
}
float myfgetmousex()
{
return ((float)getvaluator(MOUSEX)-oldxorg)/oldxsize;
}
float myfgetmousey()
{
return ((float)getvaluator(MOUSEY)-oldyorg)/oldysize;
}
main(argc,argv)
int argc;
char **argv;
{
int menu;
short val, i;
float initx, inity;
float newx, newy;
float dx, dy;
float initrad, newrad, dr;
if(argc<2) {
fprintf(stderr,"usage: warp inimage.rgb [file.key]\n");
exit(1);
}
drawgrid = 0;
warpradius = 0.2;
dim = DEFMESHRES;
initwarp();
if(argc == 3)
readkeys(argv[2]);
else {
for(i=0; i<NKEYS; i++)
loadkey(i);
}
sizeofimage(argv[1],&xsize, &ysize);
keepaspect(xsize,ysize);
aspect = xsize/(float)ysize;
if(getgdesc(GD_TEXTURE) == 0) {
fprintf(stderr,"sorry - phwarp needs texture mapping\n");
exit(1);
}
winopen("phwarp");
makeframe();
doublebuffer();
RGBmode();
gconfig();
cpack(0x00000000);
clear();
swapbuffers();
textureread(argv[1],1);
settexture(0);
qmouse();
qdevice(ESCKEY);
qdevice(UPARROWKEY);
qdevice(DOWNARROWKEY);
qdevice(F1KEY);
qdevice(F2KEY);
qdevice(F3KEY);
qdevice(F4KEY);
qdevice(F5KEY);
qdevice(F6KEY);
qdevice(F7KEY);
qdevice(F8KEY);
qdevice(F12KEY);
drawmesh();
menu = defpup("phwarp %t|restore image|pos warp|size warp|toggle mesh|save image|store out.key|save movie|help|quit");
while(1) {
switch(qread(&val)) {
case REDRAW:
makeframe();
drawmesh();
break;
case ESCKEY:
exit(0);
break;
case F1KEY:
if(val)
dofunc(0);
break;
case F2KEY:
if(val)
dofunc(1);
break;
case F3KEY:
if(val)
dofunc(2);
break;
case F4KEY:
if(val)
dofunc(3);
break;
case F5KEY:
if(val)
dofunc(4);
break;
case F6KEY:
if(val)
dofunc(5);
break;
case F7KEY:
if(val)
dofunc(6);
break;
case F8KEY:
if(val)
dofunc(7);
break;
case F12KEY:
if(val)
toggleperformance();
break;
case LEFTMOUSE:
if(val) {
switch(warpmode) {
case WARP_POS:
initx = myfgetmousex();
inity = myfgetmousey();
posweightmesh(initx,inity,warpradius);
while(getbutton(LEFTMOUSE)) {
newx = myfgetmousex();
newy = myfgetmousey();
dx = newx-initx;
dy = newy-inity;
posmovemesh(dx,dy);
drawmesh();
initx = newx;
inity = newy;
}
break;
case WARP_SIZE:
initx = myfgetmousex();
inity = myfgetmousey();
initrad = 0;
sizeweightmesh(initx,inity,warpradius);
while(getbutton(LEFTMOUSE)) {
newx = myfgetmousex();
newy = myfgetmousey();
dx = aspect*(newx-initx);
dy = newy-inity;
newrad = sqrt_sum_sq(dx,dy);
dr = newrad-initrad;
if(newy>inity)
sizemovemesh(dr);
else
sizemovemesh(-dr);
drawmesh();
initrad = newrad;
}
break;
}
}
break;
case MIDDLEMOUSE:
if(val) {
while(getbutton(MIDDLEMOUSE))
setnsteps();
fprintf(stderr,"nsteps is %d\n",nsteps);
}
break;
case UPARROWKEY:
if(val) {
warpradius *= RADSCALE;
fprintf(stderr,"warp rad is %f\n",warpradius);
}
break;
case DOWNARROWKEY:
if(val) {
warpradius /= RADSCALE;
fprintf(stderr,"warp rad is %f\n",warpradius);
}
break;
case MENUBUTTON:
if(val) {
switch(dopup(menu)) {
case 1:
initwarp();
drawmesh();
break;
case 2:
warpmode = WARP_POS;
break;
case 3:
warpmode = WARP_SIZE;
break;
case 4:
drawgrid = 1-drawgrid;
drawmesh();
break;
case 5:
fprintf(stderr,"saving window to temp.rgb....");
savewindow("temp.rgb");
fprintf(stderr,"done\n");
break;
case 6:
writekeys("out.key");
break;
case 7:
savemovie("warp.mov");
break;
case 8:
printhelp();
break;
case 9:
exit(0);
break;
}
}
}
}
}
makeframe()
{
float x1, y1, x2, y2;
reshapeviewport();
if(fullmode) {
x1 = -(float)oldxorg/oldxsize;
x2 = (float)(XMAXSCREEN-oldxorg)/oldxsize;
y1 = -(float)oldyorg/oldysize;
y2 = (float)(YMAXSCREEN-oldyorg)/oldysize;
ortho2(x1,x2,y1,y2);
} else {
getsize(&oldxsize,&oldysize);
getorigin(&oldxorg,&oldyorg);
ortho2(0.0,1.0,0.0,1.0);
}
}
toggleperformance()
{
fullmode = 1-fullmode;
if(fullmode) {
getsize(&oldxsize,&oldysize);
getorigin(&oldxorg,&oldyorg);
keepaspect(5,4);
winconstraints();
winposition(0,XMAXSCREEN,0,YMAXSCREEN);
} else {
keepaspect(xsize,ysize);
winconstraints();
winposition(oldxorg,oldxorg+oldxsize-1,oldyorg,oldyorg+oldysize-1);
}
}
drawmesh()
{
int x, y;
cpack(0x00000000);
clear();
if(drawgrid) {
cpack(0xffe0e0e0);
for(y=0; y<(dim-1); y++) {
for(x=0; x<(dim-1); x++) {
bgnclosedline();
v2f((float *)&pt[y+0][x+0].warp);
v2f((float *)&pt[y+0][x+1].warp);
v2f((float *)&pt[y+1][x+1].warp);
v2f((float *)&pt[y+1][x+0].warp);
endclosedline();
}
}
} else {
settexture(1);
mytmcolor(0x00ffffff);
for(y=0; y<(dim-1); y++) {
for(x=0; x<(dim-1); x++) {
bgnpolygon();
t2f((float *)&pt[y+0][x+0].orig);
v2f((float *)&pt[y+0][x+0].warp);
t2f((float *)&pt[y+0][x+1].orig);
v2f((float *)&pt[y+0][x+1].warp);
t2f((float *)&pt[y+1][x+1].orig);
v2f((float *)&pt[y+1][x+1].warp);
t2f((float *)&pt[y+1][x+0].orig);
v2f((float *)&pt[y+1][x+0].warp);
endpolygon();
}
}
settexture(0);
}
if(movief)
addscreenframe();
swapbuffers();
}
initwarp()
{
int i, j;
for (i=0; i<dim; i++)
for (j=0; j<dim; j++) {
pt[i][j].orig.x = pt[i][j].warp.x = (float)j/(dim-1);
pt[i][j].orig.y = pt[i][j].warp.y = (float)i/(dim-1);
}
}
float wfunc(dist,rad)
float dist, rad;
{
float ret;
ret = 1.0-dist/rad;
if(ret<0.0)
return 0.0;
return ease(ret);
}
posweightmesh(x, y, r)
float x, y, r;
{
int i, j;
warpPoint *p;
float dist;
float dx, dy;
for (i=0; i<dim; i++) {
for (j=0; j<dim; j++) {
p = &pt[i][j];
dx = p->warp.x-x;
dy = p->warp.y-y;
dist = sqrt_sum_sq(aspect*dx,dy);
p->wgt.x = p->wgt.y = wfunc(dist,r);
}
}
}
posmovemesh(dx, dy)
float dx, dy;
{
int i, j;
warpPoint *p;
for (i=0; i<dim; i++) {
for (j=0; j<dim; j++) {
p = &pt[i][j];
p->warp.x += p->wgt.x*dx;
p->warp.y += p->wgt.y*dy;
}
}
}
sizeweightmesh(x, y, r)
float x, y, r;
{
int i, j;
warpPoint *p;
float dist;
float dx, dy;
for (i=0; i<dim; i++) {
for (j=0; j<dim; j++) {
p = &pt[i][j];
dx = p->warp.x-x;
dy = p->warp.y-y;
dist = sqrt_sum_sq(aspect*dx,dy);
p->wgt.x = dx * wfunc(dist,r);
p->wgt.y = dy * wfunc(dist,r);
}
}
}
sizemovemesh(dr)
float dr;
{
int i, j;
warpPoint *p;
dr = 5.0*dr;
for (i=0; i<dim; i++) {
for (j=0; j<dim; j++) {
p = &pt[i][j];
p->warp.x += p->wgt.x*dr;
p->warp.y += p->wgt.y*dr;
}
}
}
/*
* library support follows
*
*
*/
myqmouse()
{
qdevice(LEFTMOUSE);
qdevice(MIDDLEMOUSE);
qdevice(RIGHTMOUSE);
}
mytmcolor(c)
long c;
{
cpack(c);
}
printhelp()
{
printf("\n\nphwarp - Paul Heckbert and Paul Haeberli team up to warp images\n\n");
printf("This program allows you to inteactively warp an image on a SGI\n");
printf("VGX machine. There two warp modes supported by this program:\n\n");
printf(" 1. Pos Warp - this warps the position of part of the image\n");
printf(" 2. Size Warp - this warps the size of part of the image\n\n");
printf("The current warp mode may be selected by interacting with\n");
printf("the menu. Depressing the left mouse button choses an orgin for\n");
printf("warping. Then, as the mouse is moved, a control grid is altered\n");
printf("using the current warp diameter. The current warp diameter can\n");
printf("be made larger, or smaller by pressing the up and down arrow\n");
printf("keys. Every two arrow clicks will double or half the size of\n");
printf("the affected area. Initially only the control mesh is displayed.\n");
printf("By selecting 'toggle mesh' the program can be made to display the\n");
printf("texture mapped image in real time.\n\n");
printf("Have fun!!\n");
}
myshiftdown()
{
if(getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY))
return 1;
else
return 0;
}
savemovie(name)
char *name;
{
long xsize, ysize;
lerpkey(0);
movief = fopen(name,"w");
if(!movief) {
fprintf(stderr,"vidtomov: can't open output file\n",name);
exit(1);
}
getsize(&xsize,&ysize);
createmovie(movief,xsize,ysize,4.0);
lerpkey(1);
lerpkey(2);
lerpkey(3);
lerpkey(0);
ringbell();
fclose(movief);
movief = 0;
}
addscreenframe()
{
long xsize, ysize;
unsigned long *lptr;
getsize(&xsize,&ysize);
lptr = (unsigned long *)malloc(xsize*ysize*sizeof(long));
lrectread(0,0,xsize-1,ysize-1,lptr);
addframe(movief,lptr,xsize,ysize);
}